/*
* Copyright 2015 Igor Maznitsa.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.igormaznitsa.nbmindmap.nb.refactoring.gui;
import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.modules.refactoring.api.ui.ExplorerContext;
import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
public final class MovePanel extends javax.swing.JPanel implements CustomRefactoringPanel {
public static final ResourceBundle BUNDLE = ResourceBundle.getBundle("com/igormaznitsa/nbmindmap/i18n/Bundle");
private static final long serialVersionUID = -5276978458284047575L;
private final AtomicBoolean initialized = new AtomicBoolean();
private final Lookup lookup;
private final FileObject[] files;
private final ChangeListener parent;
private final Map<Project, String[]> cachedFolders = new HashMap<Project, String[]>();
public MovePanel(final Lookup lookup, final FileObject[] files, final ChangeListener parent) {
initComponents();
this.lookup = lookup;
this.files = files;
this.parent = parent;
this.comboProjects.setRenderer(new ProjectCellRenderer());
this.comboProjects.removeAllItems();
this.comboFolders.setRenderer(new FolderCellRenderer());
this.comboFolders.removeAllItems();
}
@Override
public void initialize() {
if (this.initialized.compareAndSet(false, true)) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
initValues();
}
});
}
}
@Override
public Component getComponent() {
return this;
}
private void initValues() {
final String text;
if (this.files.length > 1) {
text = String.format(BUNDLE.getString("MovePanel.multiFileText"), Integer.toString(this.files.length));
}
else {
text = String.format(BUNDLE.getString("MovePanel.singleFileText"), this.files[0].getName());
}
this.labelMessage.setText(text);
final List<Project> projects = new ArrayList<Project>();
for (final Project p : OpenProjects.getDefault().getOpenProjects()) {
projects.add(p);
}
final ComboBoxModel<Project> projectModel = new DefaultComboBoxModel<Project>(projects.toArray(new Project[projects.size()]));
final ItemListener listener = new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (comboProjects.equals(e.getSource())) {
updateFolders();
parent.stateChanged(null);
}
else if (comboFolders.equals(e.getSource())) {
parent.stateChanged(null);
}
}
};
this.comboProjects.addItemListener(listener);
this.comboFolders.addItemListener(listener);
this.comboProjects.setModel(projectModel);
this.comboProjects.setSelectedItem(FileOwnerQuery.getOwner(this.files[0]));
updateFolders();
final ExplorerContext explorerContext = this.lookup.lookup(ExplorerContext.class);
if (explorerContext != null) {
final Node targetNode = explorerContext.getTargetNode();
if (targetNode != null) {
final DataObject dobj = targetNode.getLookup().lookup(DataObject.class);
if (dobj != null) {
final FileObject fo = dobj.getPrimaryFile();
if (fo != null && fo.isValid() && fo.isFolder()) {
final Project proj = FileOwnerQuery.getOwner(fo);
if (proj != null) {
this.comboProjects.setSelectedItem(proj);
this.comboFolders.setSelectedItem(FileUtil.getRelativePath(proj.getProjectDirectory(), fo));
}
}
}
}
}
}
public FileObject getTarget() {
final Project project = (Project) this.comboProjects.getSelectedItem();
final String folder = (String) this.comboFolders.getSelectedItem();
if (project == null || folder == null) {
return null;
}
else {
return project.getProjectDirectory().getFileObject(folder);
}
}
private void updateFolders() {
final Project project = (Project) this.comboProjects.getSelectedItem();
if (project == null) {
this.comboFolders.setModel(new DefaultComboBoxModel());
}
else {
String[] foldersForProject = this.cachedFolders.get(project);
if (foldersForProject == null) {
foldersForProject = collectAllFoldersForProject(project);
this.cachedFolders.put(project, foldersForProject);
}
final ComboBoxModel<String> folderModel = new DefaultComboBoxModel<String>(foldersForProject);
this.comboFolders.setModel(folderModel);
if (folderModel.getSize() > 0) {
this.comboFolders.setSelectedIndex(0);
}
}
}
private String[] collectAllFoldersForProject(final Project project) {
final List<String> result = new ArrayList<String>();
getFolders(project.getProjectDirectory(), project.getProjectDirectory(), result);
return result.toArray(new String[result.size()]);
}
private void getFolders(final FileObject root, final FileObject folder, final List<String> result) {
for (final FileObject c : folder.getChildren()) {
if (c.isFolder()) {
result.add(FileUtil.getRelativePath(root, c));
getFolders(root, c, result);
}
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
labelProject = new javax.swing.JLabel();
comboProjects = new javax.swing.JComboBox();
labelFolder = new javax.swing.JLabel();
comboFolders = new javax.swing.JComboBox();
labelMessage = new javax.swing.JLabel();
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/igormaznitsa/nbmindmap/i18n/Bundle"); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(labelProject, bundle.getString("MovePanel.labelProject.text")); // NOI18N
comboProjects.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
org.openide.awt.Mnemonics.setLocalizedText(labelFolder, bundle.getString("MovePanel.labelFolder.text")); // NOI18N
comboFolders.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
labelMessage.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/igormaznitsa/nbmindmap/icons/logo/logo16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(labelMessage, "..."); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(labelMessage, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(3, 3, 3)
.addComponent(labelFolder)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(comboFolders, 0, 319, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(labelProject)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(comboProjects, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(labelMessage)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(comboProjects, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(labelProject))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(comboFolders, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(labelFolder))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JComboBox comboFolders;
private javax.swing.JComboBox comboProjects;
private javax.swing.JLabel labelFolder;
private javax.swing.JLabel labelMessage;
private javax.swing.JLabel labelProject;
// End of variables declaration//GEN-END:variables
}